﻿/*
 * GamePersistenceHandler.cs
 * 
 * Purpose:
 * Handles serializing and deserializing Game objects for persistence.
 * 
 * Revision Log:
 * 08-SEP-12, C. Bush, First Draft.
 * 12-SEP-12, Q. Nguyen
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Air_Trafic_Control.Domain.Entity;
using System.IO;
using System.Xml.Serialization;

namespace Air_Trafic_Control.Domain.Persistence
{
    public class GamePersistenceHandler
    {
        private List<Game> games = new List<Game>();
        private string directory = "";
        private string fullDirectoryPath = "";

        /// <summary>
        /// Creates a new GamePersistenceHandler.
        /// </summary>
        /// <param name="directory"></param>
        /// <param name="playerName"></param>
        public GamePersistenceHandler(string directory, string playerName)
        {
            List<string> gameNames = new List<string>();
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(Game));
            TextReader textReader = null;
            
            // Set the directory
            this.directory = directory;
            this.fullDirectoryPath = directory + "\\" + playerName.Replace(' ', '_');

            // Verify there is a directory for the player
            try
            {
                if (!(Directory.Exists(fullDirectoryPath)))
                {
                    Directory.CreateDirectory(fullDirectoryPath);
                }
            }
            catch (Exception e)
            {
                System.Console.WriteLine("[GamerPersistenceHandler.GamePersistenceHandler] Exception encountered while verifying the existence of directory \'" + fullDirectoryPath + "\'.");
                System.Console.WriteLine(e.Message);
            }

            try
            {
                // If the file does not exist, create it
                if (!(File.Exists(fullDirectoryPath + "\\GameList.gph")))
                {
                    File.Create(fullDirectoryPath + "\\GameList.gph").Close();
                }
            }
            catch (Exception e)
            {
                System.Console.WriteLine("[GamePersistenceHandler.GamePersistenceHanlder] Exception encountered while creating new GameList.gph file.");
                System.Console.WriteLine(e.Message);
            }

            try
            {
                // Read the lines of the file -- each line has a user name on it
                foreach (string nextLine in File.ReadLines(fullDirectoryPath + "\\GameList.gph"))
                {
                    gameNames.Add(nextLine);
                }
            }
            catch (Exception e)
            {
                System.Console.WriteLine("[GamePersistenceHandler.GamePersistenceHanlder] Exception encountered while reading lines from GameList.gph file.");
                System.Console.WriteLine(e.Message);
            }

            try
            {
                // Get each file and deserialize the Game object from it
                foreach (string gameName in gameNames)
                {
                    textReader = new StreamReader(File.Open(fullDirectoryPath + "\\" + gameName + ".game", FileMode.Open, FileAccess.Read));

                    this.games.Add((Game)xmlSerializer.Deserialize(textReader));

                    textReader.Close();
                }
            }
            catch (Exception e)
            {
                System.Console.WriteLine("[GamePersistenceHandler.GamePersistenceHanlder] Exception encountered while deserializing game files.");
                System.Console.WriteLine(e.Message);
            }
        }

        /// <summary>
        /// Accessor for games list.
        /// </summary>
        public List<Game> Games
        {
            get
            {
                return this.games;
            }
        }

        /// <summary>
        /// Add a new game to the list. If the game already exists, false is returned. True is returned otherwise.
        /// </summary>
        /// <param name="game">The new game to be added.</param>
        /// <returns>True if the game does not already exist and is added. False, otherwise.</returns>
        public bool AddGame(Game game)
        {
            foreach (Game g in this.games)
            {
                if (g.Name.Equals(game.Name))
                {
                    return false;
                }
            }

            this.games.Add(game);
            return true;
        }

        /// <summary>
        /// Remove a game.
        /// </summary>
        /// <param name="gameName">The name of the game to be removed.</param>
        /// <returns>True if the game is found and removed. False, otherwise.</returns>
        public bool RemoveGame(string gameName)
        {
            Game gameToRemove = null;
            foreach (Game g in this.games)
            {
                if (g.Name.Equals(gameName))
                {
                    gameToRemove = g;
                    break;
                }
            }

            if (gameToRemove != null)
            {
                this.games.Remove(gameToRemove);
                return true;
            }

            return false;
        }

        /// <summary>
        /// Updates the game list file and then serializes all the games to their own files.
        /// </summary>
        /// <returns>True if the operation is successful.</returns>
        public bool SaveGames()
        {
            List<string> gameNames = new List<string>();
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(Game));
            TextWriter textWriter = null;

            try
            {
                // Update the GameList.gph file with the current list of names. Replace spaces with underscores.
                textWriter = new StreamWriter(File.Open(this.fullDirectoryPath + "\\GameList.gph", FileMode.Create, FileAccess.Write));

                foreach (Game g in this.games)
                {
                    textWriter.WriteLine(g.Name.Replace(' ', '_'));
                }

                textWriter.Close();
            }
            catch (Exception e)
            {
                System.Console.WriteLine("[GamePersistenceHandler.SaveGames] Exception encountered while writing game list to GameList.gph.");
                System.Console.WriteLine(e.Message);

                return false;
            }

            // Now, let's serialize all the games to their own files.
            foreach (Game g in this.games)
            {
                try
                {
                    textWriter = new StreamWriter(File.Open(this.fullDirectoryPath + "\\" + g.Name.Replace(' ', '_') + ".game", FileMode.Create, FileAccess.Write));

                    xmlSerializer.Serialize(textWriter, g);

                    textWriter.Close();
                }
                catch (Exception e)
                {
                    System.Console.WriteLine("[GamePersistenceHandler.SaveGames] Exception encountered while serializing games to persistence.");
                    System.Console.WriteLine(e.Message);
                    return false;
                }
            }

            return true;
        }
    }
}
